WICONF.initDragList={
    percount: 20,// 每页显示的数据条数
    delay: 1000// 加载动画保持时间
};
/**
 * @widoc $.fn.initDragList
 * @namespace comp
 * @des 拖拽分页：将在 el 中添加 wi-drag-before, wi-drag-after，el 中应只有一个高度为 100% 的非定位元素。
 <p class="t_red">注意：el 不能通过 box-flex 控制高度，将引起拖拽效果的异常。</p>
 * 组件配置，在使用组件前调用：
 <pre class="des-conf"> $.setWiConf('initDragList',{
    percount: 20,// 每页显示的数据条数
    delay: 1000// 加载动画保持时间
 });</pre>
 * @depends initDragLoader/$.fn.initDragLoader
 * @type function
 * @param {object} opts
 * @param {int=} opts.percount 每页显示的数据条数，默认为 20
 * @param {Array=} opts.data 前台分页时的数据源，优先级高于 opts.url
 * @param {string=} opts.url 后台分页时的请求 url。opts.data 定义时此属性失效
 * @param {object=} opts.args 后台分页时发送到 opts.url 的请求参数
 * @param {function=} opts.afterFlip 每次翻页后的回调函数 function(datalist,pageObj,data)
 *   - datalist {Array} 请求页所有数据
 *   - pageObj {object} 分页对象
 *       pageObj.totalpage 总页数
 *       pageObj.curpage 当前页码（从1开始）
 *       pageObj.percount 每页数据条数
 *       pageObj.totalcount 总数据数
 *   - data {object} 后台分页时，每次分页请求到的后台数据的 data 部分；前台分页时，所有数据的集合
 * @param {object=} opts.requestOpts 调用 $.request 的参数 TODO 需要解决与 opts.url 等冲突的项
 * @param {int=} opts.delay 加载动画保持时间
 * @param {int=} opts.contEl
 * @param {boolean=} opts.prompt 无数据时是否显示提示，默认为 true
 * @param {string=} opts.promptMsg 无数据时提示信息
 * @return {object|undefined} obj
 * @rtn {function} obj.fReset(opts) 重置对象
 * @rtn {object} obj.page 获得分页信息
 *   - {int} obj.page.percount 每页条数
 *   - {int} obj.page.totalpage 总页数
 *   - {int} obj.page.curpage 当前页码
 *   - {int} obj.page.totalcount 总数据条数
 */
$.fn.initDragList = function(opts){
    var el = $(this);
    var conf = WICONF.initDragList, api;
    opts = $.extend({
        percount: conf.percount,// 每页显示的数据条数
        //url:'',// 后台分页时请求的url
        args: {},// 后台分页时的参数
        //data:[],// 前台分页时的数据源
        //afterFlip:function(datalist,pageObj,data),// 每次翻页后的回调函数，datalist:当前页数据；pageObj:当前分页信息；data
        requestOpts: {},// TODO 需要解决与 opts.url 等冲突的项
        delay: conf.delay,// 加载动画保持时间
        contEl: '',
        prompt: true,// 无数据时是否显示提示
        promptMsg:'' //无数据时提示信息
    }, opts);
    var oPage = {};
    var dragLoaderObj;
    /**
     * 绘制分页及触发回调
     * @param dl {Array} 请求页所有数据
     * @param pageNum {int} 页码(从 1 开始)
     * @param totalcount {int} 数据总数
     * @param data {object=} 后台分页时，每次分页请求到的后台数据的 data 部分
     */
    var fDrawDom = function(dl, pageNum, totalcount, data){
        oPage.totalpage = Math.ceil(totalcount / opts.percount);
        oPage.curpage = pageNum;
        oPage.totalcount = totalcount;
        dragLoaderObj.setDragUpDisabled(pageNum == oPage.totalpage);// 当前页是最后一页，禁用想上拖拽，否则启用
        opts.prompt && jqLoadmore.html(oPage.totalpage <= pageNum ? (opts.promptMsg || '没有更多数据了') : '向上拖拽显示更多数据');
        opts.afterFlip && opts.afterFlip(dl, oPage, data, jqCont);// 翻页后的回调函数
        if(dragLoaderObj.isLoading()){// 如果正处于加载中，则延长动画时间，加判断是为了避免初始化时立即滑动，会被定时器中断
            setTimeout(function(){
                dragLoaderObj.reset();
            }, opts.delay);
        }
        else{
            // 原本使用 jqCont.get(0).scrollIntoView()，带底部菜单的页面在 appcan 调试时，整个 win 向上偏移（浏览器和真机没有问题），暂未确定是否与 dragLoaderObj.isLoading() 冲突，故放在 else 中
            if(pageNum === 1){
                // 直接调整 scrollTop 不能生效
                setTimeout(function(){
                    jqCont.parent().scrollTop(0);
                },0);
            }
        }
    };
    var goPage = function(pageNum, type){// 跳转到第几页；type:init,refresh
        var _data = opts.data,
            fRequestCb;// 后台请求回调
        // init,refresh 不需判断页码
        if(type !== 'init' && type !== 'refresh' &&
            oPage.totalpage != undefined && pageNum > oPage.totalpage) return;// 已经完成最后一页的请求
        if(_data){// 前台分页
            var startNo = (pageNum - 1) * opts.percount
                , len = _data.length;
            fDrawDom(_data.slice(startNo, Math.min(len, startNo + opts.percount)), pageNum, len, _data);
        }
        else{
            fRequestCb = function(data){
                fDrawDom(data['retlist'], pageNum, data['totalcount'], data);
            };
            $.request($.extend({}, opts.requestOpts, {
                onSuccess: fRequestCb,
                showloading: type === 'init',// init 需显示加载动画
                ajaxOpts: {
                    url: opts.url,
                    data: $.extend({
                        curpage: pageNum,// 从1开始
                        percount: opts.percount
                    }, opts.args)
                }
            }));
        }
    };
    var fReset = function(cusOpts){
        if(cusOpts){
            $.extend(opts, cusOpts);
            // 先扩展所有属性，再处理数据相关属性：url,args,data
            if(cusOpts.url){
                opts.url = cusOpts.url;
                opts.data = undefined;
            }
            else if(cusOpts.data){
                opts.data = cusOpts.data;
                opts.url = undefined;
            }
            if(cusOpts.args) opts.args = $.extend({}, cusOpts.args);
            oPage.percount = opts.percount;
        }
        if(!opts.data && !opts.url) return;// 没有定义数据源时不进行数据部分绘制，用于支持初始化时不带入数据
        goPage(1, 'init');
    };
    var jqCont, jqLoadmore;// 内容元素，信息提示元素
    var init = function(){
        el.html('<div>' +
            '<div class="wi-drag-cont">' + opts.contEl + '</div>' +
            (opts.prompt ? '<div class="wi-drag-loadmore"></div>' : '') +
            '</div>');
        jqCont = el.find('.wi-drag-cont');
        jqLoadmore = el.find('.wi-drag-loadmore');
        dragLoaderObj = el.initDragLoader({
            onDragDownStatus: function(status, dragger){
                if(status == 'load'){
                    goPage(1, 'refresh');
                }
            }
            , onDragUpStatus: function(status, dragger){
                if(status == 'load'){
                    goPage(oPage.curpage + 1);
                }
            }
        });
        fReset(opts);
    };
    api = {
        page: oPage,
        fReset: fReset
    };// 返回的接口对象
    init();
    return api;
};